#include "mem_sal.h"
#include "mem_inner.h"
#if defined (CONFIG_OS_ENABLE)
#include "os_sal.h"
#endif


/* 内存管理-SRAM2 */


#if CONFIG_MEM_AREA_SRAM2_ENABLE

#warning "SRAM2 access fail, unknow reason"

#define MEM_NAME        "SRAM2"
#define MEM_HEAP_SIZE   (CONFIG_MEM_SRAM2_HEAP_SIZE * 1024)


__ALIGNED(8) static uint8_t mem_heap_buff[MEM_HEAP_SIZE] __AT_RAM_SRAM2(0x30020000);


#if defined (CONFIG_MEM_TYPE_TLSF)
#include "tlsf/tlsf.h"
extern _mem_sal_opt mem_tlsf_sal_opt;
static const _mem_sal_opt *mem_sal_opt = &mem_tlsf_sal_opt;
static tlsf_t *mem_obj = NULL;
#elif defined (CONFIG_MEM_TYPE_FREERTOS)
#include "./free4/free4.h"
extern const _mem_sal_opt mem_free4_sal_opt;
static const _mem_sal_opt *mem_sal_opt = &mem_free4_sal_opt;
static _free4_obj_t free4_obj_t;
static _free4_obj_t *mem_obj = &free4_obj_t;
#elif defined (CONFIG_MEM_TYPE_RTX5)
#include "./rtx5/rtx_memory.h"
extern const _mem_sal_opt mem_rtx5_sal_opt;
static const _mem_sal_opt *mem_sal_opt = &mem_rtx5_sal_opt;
static _rtx5_obj_t rtx5_obj;
static _rtx5_obj_t *mem_obj = &rtx5_obj;
#elif defined (CONFIG_MEM_TYPE_THREADX)
#include "./tx/tx_memory.h"
extern const _mem_sal_opt mem_tx_sal_opt;
static const _mem_sal_opt *mem_sal_opt = &mem_tx_sal_opt;
static TX_BYTE_POOL_OBJ mem_pool_obj;
static TX_BYTE_POOL_OBJ *mem_obj = &mem_pool_obj;
#else
  #error "memory type not support!"
#endif



/* export func */

/**
 * @brief 初始化
 * 
 */
void mem_sram2_init(void)
{
    void *ret;

    int i;

    for (i = 0; i < 10; i++)
    {
        mem_heap_buff[i] = i;
    }

    for (i = 0; i < 10; i++)
    {
        if (mem_heap_buff[i] != i)
        {
            printf("reread err in [%d] = %d", i, mem_heap_buff[i]);
        }
    }
    

    ret = mem_sal_opt->func_init(mem_obj, mem_heap_buff, mem_heap_buff + MEM_HEAP_SIZE);
    if (ret)
    {
        printf("mem_sal_init fail\r\n");
    }
    else
    {
        mem_obj = ret;
    }
    printf("mem sram2 init = 0x%08X \r\n", (uint32_t)mem_obj);
}

/**
 * @brief 内存释放
 * 
 * @param ptr 
 */
void mem_sram2_free(void *ptr)
{
    mem_lock();
    mem_sal_opt->func_free(mem_obj, ptr);
    mem_unlock();
}

/**
 * @brief 内存申请
 * 
 * @param bytes 
 * @return void* 
 */
void *mem_sram2_malloc(size_t bytes)
{
    void *ptr = NULL;

    mem_lock();
    ptr = mem_sal_opt->func_malloc(mem_obj, bytes);
    mem_unlock();
    return ptr;
}

/**
 * @brief 内存重置
 * 
 * @param ptr 
 * @param bytes 
 * @return void* 
 */
void *mem_sram2_realloc(void *ptr, size_t bytes)
{
    mem_lock();
    ptr = mem_sal_opt->func_realloc(mem_obj, ptr, bytes);
    mem_unlock();
    return ptr;
}

/**
 * @brief 块内存申请
 * 
 * @param cnt 
 * @param bytes 
 * @return void* 
 */
void *mem_sram2_calloc(size_t cnt, size_t bytes)
{
    void *ptr = NULL;
    size_t size;

    mem_lock();
    size = cnt * bytes;
    ptr = mem_sal_opt->func_malloc(mem_obj, size);
    if (ptr)
    {
        memset(ptr, 0x00, size);
    }
    mem_unlock();
    return ptr;
}

/**
 * @brief 内存使用情况
 * 
 * @param info 
 */
void mem_sram2_get_info(_mem_sal_info_t *info)
{
    uint32_t total, used, used_max;
    if (info == NULL) return ;

    mem_lock();
    mem_sal_opt->func_get_info(mem_obj, &total, &used, &used_max);
    info->total = total;
    info->used = used;
    info->used_max = used_max;
    info->name = (char*)MEM_NAME;
    mem_unlock();
}

/**
 * @brief 内存算法名
 * 
 * @return char* 
 */
char *mem_sram2_get_name(void)
{
    return (char*)mem_sal_opt.name;
}

/**
 * @brief 获取内存操作句柄
 * 
 * @return _mem_sal_opt* 
 */
_mem_sal_opt *mem_sram2_get_opt(void)
{
    return (_mem_sal_opt*)mem_sal_opt;
}


#endif // CONFIG_MEM_AREA_sram2_ENABLE



